/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Portions created by the Initial Developer are
 * Copyright (C) 2012 the Initial Developer.
 * All Rights Reserved.
 *
 * The Original Code is this.
 *
 * The Initial Developer of the Original Code is the author below.
 */
/**
 * @file SharedRecord.cpp
 * @brief auto generated.
 * @author K.Ozaki
 * @date 2011/07/21
 */

#include "semi/SharedRecord.h"

namespace semi {

SharedRecord::SharedRecord(std::string filename, int recsize, int reccount,
        bool lk) :
    SharedContext::SharedContext(filename, (recsize * reccount), lk, true) { // stable

    this->recSize = recsize;
    this->recCount = reccount;
    this->index = 0; // first
}

SharedRecord::~SharedRecord() {
    this->end();
}

void SharedRecord::get(void * ret, int idx, int cnt) {
    return this->read(ret, idx, cnt, true);
}

//void * SharedRecord::read(int idx, int cnt) {
//    return this->read(idx, cnt, false);
//}

void SharedRecord::read(void * ret, int idx, int cnt, bool lk) {
    if (idx < 0)
        idx = this->index;
    if (this->recCount < idx)
        idx = this->recCount;
    if (cnt < 1)
        cnt = 1;
    if (this->recCount < idx + cnt)
        cnt = this->recCount - idx;

    //    void * ret = malloc((this->recSize * cnt));

    if (lk)
        this->lock();

    long off = ((this->recSize * idx) / this->sMem.psize) * this->sMem.psize;
    long len = ((this->recSize * idx) - off) + (this->recSize * cnt);
    void * ptr = this->sMem.get(off, len, PROT_READ);
    ptr = (void *) ((int) ptr + ((this->recSize * idx) - off));

    std::cout << "ptr " << std::string((char*) ptr) << " " << ptr << std::endl;
    memcpy(ret, ptr, (this->recSize * cnt));
    // ptr = 0;
    this->sMem.end();

    //    std::cout << "ret " << std::string((char*) ret) << " " << ret << std::endl;

    //    free( ret);
    //    return ret;
}

void SharedRecord::set(void * st, int idx, int cnt) {

    //    std::cout << " SharedRecord set index:" << this->index << " recSize:"
    //            << this->recSize << " recCount:" << this->recCount << " idx:"
    //            << idx << " cnt:" << cnt << std::endl;

    if (idx < 0)
        idx = this->index;
    if (cnt < 1)
        cnt = 1;
    if (this->recCount < idx + cnt)
        cnt = this->recCount - idx;

    void* dist = malloc(this->recSize * cnt);
    memcpy(dist, st, (this->recSize * cnt));

    long off = ((this->recSize * idx) / this->sMem.psize) * this->sMem.psize;
    long len = ((this->recSize * idx) - off) + (this->recSize * cnt);

    this->lock();

    void * ptr = this->sMem.get(off, len, PROT_WRITE);

    std::cout << "  SharedRecord set start " << (int) ptr << " poff:" << off
            << " off:" << ((this->recSize * idx) - off) << std::endl;

    ptr = (void *) ((int) ptr + ((this->recSize * idx) - off));

    memcpy(ptr, dist, (this->recSize * cnt));
    this->sMem.end();

    free(dist);
}

}
